package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.dao.TCodeDao;
import com.ruoyi.system.domain.dto.TCodeDto;
import com.ruoyi.system.domain.po.*;
import com.ruoyi.system.domain.vo.TCodeVo;
import com.ruoyi.system.mapper.TCodeMapper;
import com.ruoyi.system.mapper.TCodeTagMapper;
import com.ruoyi.system.mapper.TTagMapper;
import com.ruoyi.system.service.TCodeServier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TCodeServierImpl implements TCodeServier {

    @Resource
    private TCodeMapper tCodeMapper;
    @Resource
    private TTagMapper tTagMapper;
    @Resource
    private TCodeTagMapper tCodeTagMapper;
    @Resource
    private TCodeDao tCodeDao;
    @Resource
    private RedisCache redisCache;

    @Override
    public Integer insertCode(TCodeDto.Insert insert) {
        TCode tCode = BeanUtil.copyProperties(insert, TCode.class);
        tCode.setId(IdUtil.getSnowflake().nextId());
        tCode.setDelFlag((byte) 0);
        tCode.setCreateBy(SecurityUtils.getUsername());
        tCode.setCreateTime(new Date());
        tCode.setPinyinSimple(PinyinUtil.getFirstLetter(insert.getText(), ""));
        tCode.setPinyinFull(PinyinUtil.getPinyin(insert.getText(), ""));
        //新增标签关联
        List<Long> tagIdList = insert.getTagIdList();
        if (CollectionUtil.isNotEmpty(tagIdList)) {
            for (Long aLong : tagIdList) {
                TCodeTag tCodeTag = new TCodeTag();
                tCodeTag.setTagId(aLong);
                tCodeTag.setCodeId(tCode.getId());
                tCodeTagMapper.insertSelective(tCodeTag);
            }
        }
        return tCodeMapper.insertSelective(tCode);
    }

    @Override
    public Integer updateCode(TCodeDto.Update update) {
        TCode tCode = BeanUtil.copyProperties(update, TCode.class);
        tCode.setUpdateBy(SecurityUtils.getUsername());
        tCode.setUpdateTime(new Date());
        List<Long> tagIdList = update.getTagIdList();
        if (CollectionUtil.isNotEmpty(tagIdList)) {
            //删除旧关联
            TCodeTagExample tCodeTagExample = new TCodeTagExample();
            tCodeTagExample.createCriteria().andCodeIdEqualTo(update.getId());
            tCodeTagMapper.deleteByExample(tCodeTagExample);
            //新增标签关联
            for (Long aLong : tagIdList) {
                TCodeTag tCodeTag = new TCodeTag();
                tCodeTag.setTagId(aLong);
                tCodeTag.setCodeId(tCode.getId());
                tCodeTagMapper.insertSelective(tCodeTag);
            }
        }
        return tCodeMapper.updateByPrimaryKeySelective(tCode);
    }

    @Override
    public Integer deleteCode(TCodeDto.Delete delete) {
        TCodeExample tCodeExample = new TCodeExample();
        tCodeExample.createCriteria().andIdIn(delete.getIdList());
        TCode tCode = new TCode();
        tCode.setDelFlag((byte) 1);
        return tCodeMapper.updateByExampleSelective(tCode, tCodeExample);
    }

    @Override
    public List<TCodeVo.Result> listCode(TCodeDto.Query list) {
        return tCodeDao.query(list.getCode(), list.getText(), list.getTagIdList());
    }

    @Override
    public void exportCode(TCodeDto.Export export) {

    }

    @Override
    public Integer insertTag(TCodeDto.TagInsert tagInsert) {
        TTag tTag = BeanUtil.copyProperties(tagInsert, TTag.class);
        tTag.setId(IdUtil.getSnowflake().nextId());
        tTag.setCreateBy(SecurityUtils.getUsername());
        tTag.setCreateTime(new Date());
        return tTagMapper.insertSelective(tTag);
    }

    @Override
    public Integer updateTag(TCodeDto.TagUpdate tagUpdate) {
        TTag tTag = BeanUtil.copyProperties(tagUpdate, TTag.class);
        tTag.setUpdateBy(SecurityUtils.getUsername());
        tTag.setUpdateTime(new Date());
        return tTagMapper.updateByPrimaryKeySelective(tTag);
    }

    @Override
    public Integer deleteTag(TCodeDto.TagDelete tagDelete) {
        TTagExample tTagExample = new TTagExample();
        tTagExample.createCriteria().andIdIn(tagDelete.getIdList());
        TTag tTag = new TTag();
        tTag.setDelFlag((byte) 1);
        return tTagMapper.updateByExampleSelective(tTag, tTagExample);
    }

    @Override
    public List<TTag> listTag(TCodeDto.QueryTag queryTag) {
        TTagExample tTagExample = new TTagExample();
        TTagExample.Criteria criteria = tTagExample.createCriteria().andDelFlagEqualTo((byte) 0);
        if (StrUtil.isNotEmpty(queryTag.getName())) {
            criteria.andNameLike("%" + queryTag.getName() + "%");
        }
        tTagExample.setOrderByClause("create_time desc");
        return tTagMapper.selectByExample(tTagExample);
    }

    @Override
    public void importCode(List<TCodeDto.Import> list) {

//        TCode tCode1 = new TCode();
//        tCode1.setDelFlag((byte) 1);
//        TCodeExample tCodeExample = new TCodeExample();
//        tCodeExample.createCriteria().andDelFlagEqualTo((byte) 0);
//        tCodeMapper.updateByExampleSelective(tCode1, tCodeExample);

        for (TCodeDto.Import importCode : list) {

            TCodeExample tCodeExample = new TCodeExample();
            tCodeExample.createCriteria().andCodeEqualTo(importCode.getCode()).andDelFlagEqualTo((byte) 0);
            TCode tCode1 = new TCode();
            tCode1.setDelFlag((byte) 1);
            tCodeMapper.updateByExampleSelective(tCode1, tCodeExample);

            TCode tCode = new TCode();
            tCode.setId(IdUtil.getSnowflake().nextId());
            tCode.setCode(importCode.getCode());
            tCode.setText(importCode.getText());
            tCode.setOperatorName(importCode.getOperatorName());
            tCode.setOptions(importCode.getOptions());
            tCode.setShowType(importCode.getShowType());
            tCode.setPinyinSimple(PinyinUtil.getFirstLetter(importCode.getText(), ""));
            tCode.setPinyinFull(PinyinUtil.getPinyin(importCode.getText(), ""));
            tCodeMapper.insertSelective(tCode);

            //判断标签
            List<String> tagList = importCode.getTag();
            if (CollectionUtil.isNotEmpty(tagList)) {
                for (String tag : tagList) {
                    TTagExample tTagExample = new TTagExample();
                    tTagExample.createCriteria().andNameEqualTo(tag).andDelFlagEqualTo((byte) 0);
                    List<TTag> tTags = tTagMapper.selectByExample(tTagExample);
                    TTag tTag = new TTag();
                    if (CollectionUtil.isEmpty(tTags)) {
                        tTag.setId(IdUtil.getSnowflake().nextId());
                        tTag.setName(tag);
                        tTagMapper.insertSelective(tTag);
                    }else {
                        tTag = tTags.get(0);
                    }
                    TCodeTag tCodeTag = new TCodeTag();
                    tCodeTag.setCodeId(tCode.getId());
                    tCodeTag.setTagId(tTag.getId());
                    tCodeTagMapper.insertSelective(tCodeTag);
                }
            }
        }
    }

    @Override
    public List<TCode> queryByCodeList(List<String> codeList) {
        TCodeExample tCodeExample = new TCodeExample();
        TCodeExample.Criteria criteria = tCodeExample.createCriteria().andDelFlagEqualTo((byte) 0);
        if (CollectionUtil.isNotEmpty(codeList)) {
            criteria.andCodeIn(codeList);
        }
        return tCodeMapper.selectByExample(tCodeExample);
    }

    @Override
    public TCodeVo.Result getCodeCache(String code) {
        //判断key是否存在
        if(!redisCache.hasKey(CacheConstants.FIRST_AID_CODE_KEY)){
            loadingCodeCache();
        }
        //非空判定
        if(StrUtil.isEmpty(code)){
            return null;
        }
        //获取code对应的CmsCodeVo.QueryList对象
        return redisCache.getCacheMapValue(CacheConstants.FIRST_AID_CODE_KEY, code);
    }

    public void loadingCodeCache() {
        List<TCodeVo.Result> list = listCode(new TCodeDto.Query());
        Map<String, TCodeVo.Result> codeMap =
                list.stream().collect(Collectors.toMap(TCodeVo.Result::getCode, Function.identity(), (k1, k2) -> k2));
        redisCache.setCacheMap(CacheConstants.FIRST_AID_CODE_KEY, codeMap);
    }

}
